#include "stdafx.h"
#include <windows.h>
#include "gen_RQ.h"
#include "wa_ipc.h"
#include <dirent.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <ShlObj.h>
#include <atlbase.h>
#include "frmConfig.h"
#include <fstream>
#include <map>

// these are callback functions/events which will be called by Winamp
int  init(void);
void config(void);
void quit(void);

//These are some variables to hold the path to the RQ AppData folder.
PWSTR* directory;
std::wstring dirStr;
std::wstring dirMedia;
std::map<int, std::string> filesByDate;

// this structure contains plugin information, version, name...
// GPPHDR_VER is the version of the winampGeneralPurposePlugin (GPP) structure
winampGeneralPurposePlugin plugin = {
	GPPHDR_VER,  // version of the plugin, defined in "gen_myplugin.h"
	PLUGIN_NAME, // name/title of the plugin, defined in "gen_myplugin.h"
	init,        // function name which will be executed on init event
	config,      // function name which will be executed on config event
	quit,        // function name which will be executed on quit event
	0,           // handle to Winamp main window, loaded by winamp when this dll is loaded
	0            // hinstance to this dll, loaded by winamp when this dll is loaded
};
// event functions follow

int init() {
	directory = new PWSTR();

	SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, directory);

	dirStr = *directory;
	dirStr += L"\\RQ";
	dirMedia = dirStr + L"\\Media";

	if (!gen_RQ::dirExists(std::string(dirMedia.begin(), dirMedia.end()))) CreateDirectory(dirMedia.c_str(), NULL);

	return 0;
}

void config() {
	Form^ configForm = gcnew gen_RQ::frmConfig();
	configForm->Show();
}

void quit() {
	RemoveDirectory(L"C:\\RQ_data");
}

namespace gen_RQ {
	std::wstring s2ws(const std::string& s)
	{
		int len;
		int slength = (int)s.length() + 1;
		len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0); 
		wchar_t* buf = new wchar_t[len];
		MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
		std::wstring r(buf);
		delete[] buf;
		return r;
	}

	void findFiles() {
		filesByDate.clear();
		std::vector<std::string> fileList;
		DIR *d;
		struct dirent *dir;
		std::string folder(dirMedia.begin(), dirMedia.end());
		d = opendir(folder.c_str());
		if (d) {
			while ((dir = readdir(d)) != NULL) {
				bool addFile = true;
				for (unsigned i = 0; i < fileList.size(); i++) {
					if (folder + "\\" + dir->d_name == fileList[i]) addFile = false;
				}
				if (dir->d_type != S_IFDIR && addFile) fileList.push_back(folder + "\\" + dir->d_name);
			}
			closedir(d);
		}


		for(unsigned i = 0; i < fileList.size(); i++) {
			HANDLE thisFile = CreateFile(s2ws(fileList[i]).c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
			FILETIME wTime;
			FILETIME cTime;
			FILETIME aTime;
			GetFileTime(thisFile, &cTime, &aTime, &wTime);
			SYSTEMTIME sTime;
			FileTimeToSystemTime(&wTime, &sTime);
			int milliseconds = (sTime.wMilliseconds) + (sTime.wSecond * 1000) + (sTime.wMinute * 60 * 1000) + (sTime.wHour * 60 * 60 * 1000);
			DWORD error = GetLastError();
			filesByDate[milliseconds] = fileList[i];
		}
	}

	void queueFiles() {
		for (std::map<int, std::string>::iterator i = filesByDate.begin(); i != filesByDate.end(); i++) {
			enqueueFileWithMetaStruct eFWMS = {0};
			eFWMS.filename = (i->second).c_str();	
			SendMessage(plugin.hwndParent,WM_WA_IPC,(WPARAM)&eFWMS,IPC_ENQUEUEFILE);
		}
	}

	bool dirExists(const std::string& dirName_in) {
		DWORD ftyp = GetFileAttributesA(dirName_in.c_str());
		if (ftyp == INVALID_FILE_ATTRIBUTES)
			return false;  //something is wrong with your path!

		if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
			return true;   // this is a directory!

		return false;    // this is not a directory!
	}
}

// This is an export function called by winamp which returns this plugin info.
// We wrap the code in 'extern "C"' to ensure the export isn't mangled if used in a CPP file.
extern "C" __declspec(dllexport) winampGeneralPurposePlugin * winampGetGeneralPurposePlugin() {
	return &plugin;
}